<template>
  <el-form ref="form" :model="model" :label-width="lw">
    <el-form-item
      :rules="item.rules"
      v-for="(item, key) in options"
      :key="key"
      :label="item.title"
      :prop="key"
    >
      <!-- 生成input -->
      <el-input
        v-model="model[key]"
        v-if="item.tag === 'input'"
        :type="item.type"
        :placeholder="item.ph"
        :maxlength="item.max"
        :disabled="item.dis"
      ></el-input>
      <!-- 生成select -->
      <el-select v-else-if="item.tag === 'select'"></el-select>
      <!-- 生成级联选择器 -->
      <el-cascader
        :options="item.value"
        :props="item.props"
        v-model="model[key]"
        :clearable='item.clearable'
        v-else-if="item.tag === 'cas'"
      ></el-cascader>
      <!-- 生成Upload -->
      <el-upload
        v-else-if="item.tag === 'upload'"
        :action="item.action"
        :headers="item.headers"
        :on-remove="(file, fileList) => handleRemove(key, fileList)"
        :on-success="(response, file, fileList) => uploadSuccess(key, fileList)"
        list-type="picture"
      >
        <el-button size="small" type="primary">点击上传</el-button>
      </el-upload>
    </el-form-item>
  </el-form>
</template>

<script>
export default {
  name: "Form",
  data() {
    return {
      /**
       * 模型数据
       */
      model: {},
    };
  },
  methods: {
    /**
     * 上传成功
     */
    uploadSuccess(key, fileList) {
      this.model[key] = fileList;
      console.log(this.model);
    },
    /**
     * 处理删除
     */
    handleRemove(key, fileList) {
      this.model[key] = fileList;
      console.log(this.model);
    },
    /**
     * 判断是否为数字类型
     */
    isNumber(value) {
      return typeof value === "number";
    },
    /**
     * 验证
     */
    async validate() {
      await this.$refs.form.validate();
      return { ...this.model };
    },
    /**
     * 重置
     */
    reset(){
      this.$refs.form.resetFields();
    },
  },
  computed: {
    /**
     * 表单配置项
     */
    options() {
      const obj = JSON.parse(JSON.stringify(this.opts)); //深拷贝
      for (const key in obj) {
        if (!Object.hasOwnProperty.call(obj, key)) continue;
        const item = obj[key]; //值
        item.tag = item.tag || "input";
        item.rules = item.rules || []; //如果之前有规则就用之前的，如果没有则赋值一个空数组
        // 如果有required字段则添加reuiqred规则
        if (
          item.required === true &&
          !item.rules.some((c) => c.required === true)
        ) {
          item.rules.unshift({
            required: true,
          });
        }
        // 添加规则消息
        for (const rule of item.rules) {
          if (rule.message) continue;
          if (rule.required) {
            rule.message = `${item.title}不能为空`;
          } else if (this.isNumber(rule.min) && this.isNumber(rule.max)) {
            rule.message = `${item.title}必须为${rule.min}-${rule.max}位`;
            item.max = item.max || rule.max;
          } else if (this.isNumber(rule.min)) {
            rule.message = `${item.title}最小长度为${rule.min}`;
          } else if (this.isNumber(rule.max)) {
            rule.message = `${item.title}最大长度为${rule.max}`;
            item.max = item.max || rule.max;
          } else if (rule.type) {
            rule.message = `${item.title}格式不正确`;
          }
        }
      }
      return obj;
    },
  },
  watch: {
    /**
     * 值有变化
     */
    value: {
      handler(value) {
        if (!value) return;
        this.$nextTick(() => {
          this.$refs.form.resetFields();
          this.model = { ...value };
        });
      },
      deep: true,
      immediate: true,
    },
  },
  props: {
    /**
     * label的宽度
     */
    lw: {
      type: String,
      default: "90px",
    },
    /**
     * form表单
     */
    value: Object,
    /**
     * 配置项
     */
    opts: {
      required: true,
      type: Object,
    },
  },
};
</script>

<style>
</style>